package com.tianji.learning.service.impl;

import cn.hutool.core.map.TolerantMap;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.*;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author 陈宽
 * @since 2025-07-02
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;
    private final CourseClient courseClient;

    @Override
    public void addQuestion(QuestionFormDTO questionDTO) {
        //1.dto转po
        InteractionQuestion bean = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
        //2.po补充userId
        bean.setUserId(UserContext.getUser());
        //3.保存
        this.save(bean);
    }

    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionDTO) {
        //0.1 查询问题是否存在
        InteractionQuestion byId = getById(id);
        if (ObjectUtils.isEmpty(byId)) {
            throw new RuntimeException("问题不存在");
        }
        //0.2 判断修改的问题是否是当前用户的
        if (!byId.getUserId().equals(UserContext.getUser())) {
            throw new RuntimeException("没有权限修改该问题");
        }
        //1.dto转po
        InteractionQuestion bean = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
        //2.po补充id
        bean.setId(id);
        //3.更新
        this.updateById(bean);
    }

    @Override
    public PageDTO<QuestionVO> questionPage(QuestionPageQuery query) {
        //参数校验，课程ID和小节ID不能同时为空
        if (query.getSectionId() == null && query.getCourseId() == null) {
            throw new RuntimeException("参数错误");
        }
        //1.通过query的(可能为空)onlyMine，courseId，sectionId来分页查询，hidden为true不查询
        Page<InteractionQuestion> page = this.lambdaQuery()
                .select(InteractionQuestion.class, tableFieldInfo -> ObjectUtil.notEqual(tableFieldInfo.getColumn(), "description"))
                .eq(InteractionQuestion::getHidden, false)
                .eq(ObjectUtils.isNotNull(query.getCourseId()), InteractionQuestion::getCourseId, query.getCourseId())
                .eq(ObjectUtils.isNotNull(query.getSectionId()), InteractionQuestion::getSectionId, query.getSectionId())
                .eq(ObjectUtils.isNotNull(query.getOnlyMine()) && query.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        //2.得到分页查询出来的records
        List<InteractionQuestion> records = page.getRecords();
        //3.遍历records，将获得(不匿名)提问者的userIds和latestAnswerIds
        Set<Long> userIds = new HashSet<>();
        Set<Long> latestAnswerIds = new HashSet<>();
        Set<Long> queryIds = new HashSet<>();
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            latestAnswerIds.add(record.getLatestAnswerId());
            queryIds.add(record.getId());
        }
        //4.通过latestAnswerIds得到回答的list
        List<InteractionReply> latestAnswers = replyMapper.selectBatchIds(latestAnswerIds);
        //4.1把list转成Map<Long,InteractionReply>
        Map<Long, InteractionReply> latestAnswerMap = latestAnswers.stream()
                .collect(Collectors.toMap(InteractionReply::getId, r -> r));
        //5.然后遍历list，将获得(不匿名)回答者的userIds
        for (InteractionReply latestAnswer : latestAnswers) {
            if (!latestAnswer.getAnonymity()) {
                userIds.add(latestAnswer.getUserId());
            }
        }
        //6.通过把两个userIds合并，远程调用UserClient的List<UserDTO> queryUserByIds
        //得到提问者和回答者的userDTO
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        //6.1.将userDTO转成Map<Long,UserDTO>
        Map<Long, UserDTO> userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        //7.创建一个QuestionVO的questionVOList
        List<QuestionVO> questionVOList = new ArrayList<>();
        //8.通过queryIds，得到swapper ，用这个查询条件给replyMapper.selectList
        QueryWrapper<InteractionReply> swrapper = new QueryWrapper<>();
        swrapper.select("question_id as id, count(1) as num")
                .in("question_id", queryIds)
                .eq("answer_id", 0)
                .eq("hidden", false)
                .groupBy("question_id");
        List<InteractionReply> swappers = replyMapper.selectList(swrapper);
        //8.1 创建一个Map<Long,Integer>
        Map<Long, Integer> swapperMap = swappers.stream().collect(Collectors.toMap(InteractionReply::getId, InteractionReply::getNum));
        //9.遍历records，装填vo数据
        for (InteractionQuestion record : records) {
            //9.0 创建一个QuestionVO
            QuestionVO vo = BeanUtils.toBean(record, QuestionVO.class);
            //9.1 根据latestAnswerId，从map中获取InteractionReply
            InteractionReply latestAnswer = latestAnswerMap.get(record.getLatestAnswerId());
            //9.2 根据InteractionReply得到userId，从map中获取UserDTO
            UserDTO latestReplyUser = latestAnswer == null ? null : userMap.get(latestAnswer.getUserId());
            //9.3 如果回答者不匿名，并且latestAnswer不为null，则获得UserDTO里面的昵称，填充 vo的latestReplyUser
            if (latestAnswer != null && !latestAnswer.getAnonymity()) {
                vo.setLatestReplyUser(latestReplyUser.getName());
            }
            //9.4 通过record，如果提问者不匿名，则获得UserDTO里面的昵称和头像，
            // 填充 vo的userName和userIcon
            if (!record.getAnonymity()) {
                vo.setUserName(userMap.get(record.getUserId()).getName());
                vo.setUserIcon(userMap.get(record.getUserId()).getIcon());
            }
            //9.5 questionVOList.add(vo)
            questionVOList.add(vo);
            //9.6 根据swapperMap和record的id，从swapperMap中获取num，填充vo的answerTimes
            if (ObjectUtils.isNotEmpty(swapperMap) && swapperMap.containsKey(record.getId())) {
                vo.setAnswerTimes(swapperMap.get(record.getId()));
            }
        }
        //10.返回PageDTO.of(page.getPages(),page.getTotal(),questionVOList);
        return PageDTO.of(page.getPages(), page.getTotal(), questionVOList);
    }

    @Override
    public QuestionVO getVoById(Long id) {
        //1.根据问题id得到po
        InteractionQuestion po = this.getById(id);
        if (ObjectUtils.isEmpty(po) || po.getHidden()) {
            return null;
        }
        //2.根据po里面的userId得到UserDTO
        UserDTO userDTO = userClient.queryUserById(po.getUserId());
        //4.创建一个QuestionVO
        QuestionVO vo = BeanUtils.toBean(po, QuestionVO.class);
        //5.填充数据
        if (ObjectUtils.isNotEmpty(userDTO) && !po.getAnonymity()) {
            vo.setUserName(userDTO.getName());
            vo.setUserIcon(userDTO.getIcon());
        }
        //6.返回vo
        return vo;
    }

    @Override
    public PageDTO<QuestionAdminVO> questionAdminPage(QuestionAdminPageQuery query) {
        //1.根据query的(可能没有的)courseName来远程调用
        // SearchClient的List<Long> queryCoursesIdByName
        //得到CIds
        List<Long> cIds = null;
        if (ObjectUtils.isNotNull(query.getCourseName())) {
            cIds = searchClient.queryCoursesIdByName(query.getCourseName());
            //1.1 如果搜索不出来课程，则返回空
            if (ObjectUtils.isEmpty(cIds)) {
                return PageDTO.empty(0L, 0L);
            }
        }
        //2.根据query的可能没有的eq status，ge beginTime，le endTime和in CIds来分页查询
        Page<InteractionQuestion> page = this.lambdaQuery()
                .in(ObjectUtils.isNotEmpty(cIds), InteractionQuestion::getCourseId, cIds)
                .eq(ObjectUtils.isNotNull(query.getStatus()), InteractionQuestion::getStatus, query.getStatus())
                .ge(ObjectUtils.isNotNull(query.getBeginTime()), InteractionQuestion::getCreateTime, query.getBeginTime())
                .le(ObjectUtils.isNotNull(query.getEndTime()), InteractionQuestion::getCreateTime, query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        //3.得到分页查询出来的records
        List<InteractionQuestion> records = page.getRecords();
        //4.遍历records，将获得提问者的userIds，course_id，（chapter_id，section_id）这两放到一起manuIds
        Set<Long> userIds = new HashSet<>();
        Set<Long> manuIds = new HashSet<>();
        Set<Long> courseIds = new HashSet<>();
        for (InteractionQuestion record : records) {
            if (ObjectUtils.isNotEmpty(record.getUserId())) {
                userIds.add(record.getUserId());
            }
            if (ObjectUtils.isNotEmpty(record.getCourseId())) {
                courseIds.add(record.getCourseId());
            }
            if (ObjectUtils.isNotEmpty(record.getChapterId())) {
                manuIds.add(record.getChapterId());
            }
            if (ObjectUtils.isNotEmpty(record.getSectionId())) {
                manuIds.add(record.getSectionId());
            }
        }
        //5.通过userIds得到UserDTOs
        List<UserDTO> userDTOs = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (ObjectUtils.isNotNull(userDTOs)) {
            userMap = userDTOs.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        //6.通过CatalogueClient的List<CataSimpleInfoDTO> batchQueryCatalogue
        // 和manuIds得到CatalogueDTOs得到chapterName，sectionName
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(manuIds);
        Map<Long, String> manuMap = new HashMap<>();
        if (ObjectUtils.isNotNull(cataSimpleInfoDTOS)) {
            manuMap = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        //7.通过CourseClient的List<CourseDTO> queryCourseByIds和userIds得到CourseDTOs
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(courseIds);
        Map<Long, CourseSimpleInfoDTO> courseSimpleMap = new HashMap<>();
        if (ObjectUtils.isNotNull(courseInfoList)) {
            courseSimpleMap = courseInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        }
        //9.创建一个QuestionVO的questionVOList
        List<QuestionAdminVO> questionVOList = new ArrayList<>();
        //10.遍历records，装填vo数据
        for (InteractionQuestion record : records) {
            //10.1 创建一个QuestionVO，toBean(po,QuestionVO.class);
            QuestionAdminVO questionVO = BeanUtils.toBean(record, QuestionAdminVO.class);
            //10.2 通过po的userId，从map中获取UserDTO的昵称
            UserDTO userDTO = userMap.get(record.getUserId());
            questionVO.setUserName(userDTO != null ? userDTO.getName() : null);
            //10.3 通过po的course_id，从map中获取CourseSimpleInfoDTO 得到课程名称
            CourseSimpleInfoDTO courseSimpleInfoDTO = courseSimpleMap.get(record.getCourseId());
            questionVO.setCourseName(courseSimpleInfoDTO.getName());
            //10.4 通过po的chapter_id，section_id，从map中获取CataSimpleInfoDTO的name
            questionVO.setChapterName(manuMap.getOrDefault(record.getChapterId(), ""));
            questionVO.setSectionName(manuMap.getOrDefault(record.getSectionId(), ""));
            //10.5 通过CourseSimpleInfoDTO的List<Long> getCategoryIds()得到分类ids
            List<Long> categoryIds = courseSimpleInfoDTO.getCategoryIds();
            //10.6 通过CategoryCache的List<String> getCategoryNameList(List<Long> ids)
            //和分类ids得到三层分类名称的拼接categoryName
            questionVO.setCategoryName(categoryCache.getCategoryNames(categoryIds));
            //10.7 questionVOList.add(vo)
            questionVOList.add(questionVO);
        }
        //11.返回PageDTO.of(page.getPages(),page.getTotal(),questionVOList);
        return PageDTO.of(page.getPages(), page.getTotal(), questionVOList);
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        /**查询问题是否存在
         判断是否是当前用户提问的
         如果不是则报错
         如果是则删除问题
         然后删除问题下的回答及评论
         */
        InteractionQuestion question = this.getById(id);
        if (ObjectUtils.isEmpty(question)) {
            throw new RuntimeException("问题不存在");
        }
        if (!question.getUserId().equals(UserContext.getUser())) {
            throw new RuntimeException("您没有权限删除该问题");
        } else {
            this.removeById(id);
        }
        replyMapper.delete(new LambdaUpdateWrapper<InteractionReply>()
                .eq(InteractionReply::getQuestionId, id));
    }

    @Override
    public QuestionAdminVO getAdminVoById(Long id) {
        // 1.根据id查询问题
        InteractionQuestion po = getById(id);
        if (ObjectUtils.isEmpty(po)) {
            return null;
        }
        // 2.转PO为VO
        QuestionAdminVO vo = BeanUtils.toBean(po, QuestionAdminVO.class);
        // 3.查询提问者信息
        Long userId = po.getUserId();
        UserDTO user = userClient.queryUserById(userId);
        if (ObjectUtils.isNotEmpty(user)) {
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        // 4.查询课程信息
        // 4.1.课程名称信息
        Long courseId = po.getCourseId();
        CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(courseId, true, true);
        // 4.2.分类信息
        if (ObjectUtils.isNotEmpty(courseInfo)) {
            vo.setCourseName(courseInfo.getName());
            List<Long> categoryIds = courseInfo.getCategoryIds();
            vo.setCategoryName(categoryCache.getCategoryNames(categoryIds));
            // 4.3.教师信息
            List<Long> teacherIds = courseInfo.getTeacherIds();
            List<UserDTO> teachers = userClient.queryUserByIds(teacherIds);
            if (ObjectUtils.isNotEmpty(teachers)) {
                vo.setTeacherName(teachers.stream().map(UserDTO::getName).collect(Collectors.joining("/")));
            }
        }
        // 5.查询章节信息
        Long chapterId = po.getChapterId();
        Long sectionId = po.getSectionId();
        List<Long> manuIds = new ArrayList<>();
        manuIds.add(chapterId);
        manuIds.add(sectionId);
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(manuIds);
        Map<Long, String> manuMap = new HashMap<>();
        if (ObjectUtils.isNotNull(cataSimpleInfoDTOS)) {
            manuMap = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        vo.setChapterName(manuMap.getOrDefault(chapterId, ""));
        vo.setSectionName(manuMap.getOrDefault(sectionId, ""));
        return vo;
    }
    @Override
    public void updateQuestionHidden(Long id, Boolean hidden) {
        InteractionQuestion po = new InteractionQuestion();
        po.setId(id);
        po.setHidden(hidden);
        updateById(po);
        //隐藏它的评论
        LambdaUpdateWrapper<InteractionReply> wrappers = new  LambdaUpdateWrapper<>();
        wrappers.eq(InteractionReply::getQuestionId, id)
                .set(InteractionReply::getHidden, hidden);
        replyMapper.update(
                null,
//                Wrappers.<InteractionReply>lambdaUpdate()
//                        .eq(InteractionReply::getQuestionId, id)
//                        .set(InteractionReply::getQuestionId, hidden)
                wrappers
        );
    }

}
